package edu.pku.sei.transformation.mtparser;

import lpg.runtime.*;

public class MTParser implements RuleAction
{
    private PrsStream prsStream = null;
    
    private boolean unimplementedSymbolsWarning = false;

    private static ParseTable prsTable = new MTParserprs();
    public ParseTable getParseTable() { return prsTable; }

    private DeterministicParser dtParser = null;
    public DeterministicParser getParser() { return dtParser; }

    private void setResult(Object object) { dtParser.setSym1(object); }
    public Object getRhsSym(int i) { return dtParser.getSym(i); }

    public int getRhsTokenIndex(int i) { return dtParser.getToken(i); }
    public IToken getRhsIToken(int i) { return prsStream.getIToken(getRhsTokenIndex(i)); }
    
    public int getRhsFirstTokenIndex(int i) { return dtParser.getFirstToken(i); }
    public IToken getRhsFirstIToken(int i) { return prsStream.getIToken(getRhsFirstTokenIndex(i)); }

    public int getRhsLastTokenIndex(int i) { return dtParser.getLastToken(i); }
    public IToken getRhsLastIToken(int i) { return prsStream.getIToken(getRhsLastTokenIndex(i)); }

    public int getLeftSpan() { return dtParser.getFirstToken(); }
    public IToken getLeftIToken()  { return prsStream.getIToken(getLeftSpan()); }

    public int getRightSpan() { return dtParser.getLastToken(); }
    public IToken getRightIToken() { return prsStream.getIToken(getRightSpan()); }

    public int getRhsErrorTokenIndex(int i)
    {
        int index = dtParser.getToken(i);
        IToken err = prsStream.getIToken(index);
        return (err instanceof ErrorToken ? index : 0);
    }
    public ErrorToken getRhsErrorIToken(int i)
    {
        int index = dtParser.getToken(i);
        IToken err = prsStream.getIToken(index);
        return (ErrorToken) (err instanceof ErrorToken ? err : null);
    }

    public void reset(ILexStream lexStream)
    {
        prsStream = new PrsStream(lexStream);
        dtParser.reset(prsStream);

        try
        {
            prsStream.remapTerminalSymbols(orderedTerminalSymbols(), prsTable.getEoftSymbol());
        }
        catch(NullExportedSymbolsException e) {
        }
        catch(NullTerminalSymbolsException e) {
        }
        catch(UnimplementedTerminalsException e)
        {
            if (unimplementedSymbolsWarning) {
                java.util.ArrayList unimplemented_symbols = e.getSymbols();
                System.out.println("The Lexer will not scan the following token(s):");
                for (int i = 0; i < unimplemented_symbols.size(); i++)
                {
                    Integer id = (Integer) unimplemented_symbols.get(i);
                    System.out.println("    " + MTParsersym.orderedTerminalSymbols[id.intValue()]);               
                }
                System.out.println();
            }
        }
        catch(UndefinedEofSymbolException e)
        {
            throw new Error(new UndefinedEofSymbolException
                                ("The Lexer does not implement the Eof symbol " +
                                 MTParsersym.orderedTerminalSymbols[prsTable.getEoftSymbol()]));
        }
    }
    
    public MTParser()
    {
        try
        {
            dtParser = new DeterministicParser(prsStream, prsTable, (RuleAction) this);
        }
        catch (NotDeterministicParseTableException e)
        {
            throw new Error(new NotDeterministicParseTableException
                                ("Regenerate MTParserprs.java with -NOBACKTRACK option"));
        }
        catch (BadParseSymFileException e)
        {
            throw new Error(new BadParseSymFileException("Bad Parser Symbol File -- MTParsersym.java. Regenerate MTParserprs.java"));
        }
    }

    public MTParser(ILexStream lexStream)
    {
        this();
        reset(lexStream);
    }

    public int numTokenKinds() { return MTParsersym.numTokenKinds; }
    public String[] orderedTerminalSymbols() { return MTParsersym.orderedTerminalSymbols; }
    public String getTokenKindName(int kind) { return MTParsersym.orderedTerminalSymbols[kind]; }            
    public int getEOFTokenKind() { return prsTable.getEoftSymbol(); }
    public IPrsStream getIPrsStream() { return prsStream; }

    /**
     * @deprecated replaced by {@link #getIPrsStream()}
     *
     */
    public PrsStream getPrsStream() { return prsStream; }

    /**
     * @deprecated replaced by {@link #getIPrsStream()}
     *
     */
    public PrsStream getParseStream() { return prsStream; }

    public Ast parser()
    {
        return parser(null, 0);
    }
        
    public Ast parser(Monitor monitor)
    {
        return parser(monitor, 0);
    }
        
    public Ast parser(int error_repair_count)
    {
        return parser(null, error_repair_count);
    }
        
    public Ast parser(Monitor monitor, int error_repair_count)
    {
        dtParser.setMonitor(monitor);

        try
        {
            return (Ast) dtParser.parse();
        }
        catch (BadParseException e)
        {
            prsStream.reset(e.error_token); // point to error token

            DiagnoseParser diagnoseParser = new DiagnoseParser(prsStream, prsTable);
            diagnoseParser.diagnose(e.error_token);
        }

        return null;
    }

    //
    // Additional entry points, if any
    //
    

    public void ruleAction(int ruleNumber)
    {
        switch (ruleNumber)
        {

            //
            // Rule 1:  goal ::= RuleSemantics
            //
            case 1:
                break;
            //
            // Rule 2:  RuleSemantics ::= RuleSemantics BasicRuleSemantics
            //
            case 2: {
                setResult(
                    new RuleSemantics(getLeftIToken(), getRightIToken(),
                                      (IRuleSemantics)getRhsSym(1),
                                      (BasicRuleSemantics)getRhsSym(2))
                );
                break;
            }
            //
            // Rule 3:  RuleSemantics ::= BasicRuleSemantics
            //
            case 3:
                break;
            //
            // Rule 4:  BasicRuleSemantics ::= def rule MODE { RuleSemanticsBody }
            //
            case 4: {
                setResult(
                    new BasicRuleSemantics(getLeftIToken(), getRightIToken(),
                                           (IMODE)getRhsSym(3),
                                           (IRuleSemanticsBody)getRhsSym(5))
                );
                break;
            }
            //
            // Rule 5:  MODE ::= SimpleMode
            //
            case 5:
                break;
            //
            // Rule 6:  MODE ::= ExtendMode
            //
            case 6:
                break;
            //
            // Rule 7:  SimpleMode ::= check
            //
            case 7: {
                setResult(
                    new CheckMode(getRhsIToken(1))
                );
                break;
            }
            //
            // Rule 8:  SimpleMode ::= enforce
            //
            case 8: {
                setResult(
                    new EnforceMode(getRhsIToken(1))
                );
                break;
            }
            //
            // Rule 9:  ExtendMode ::= Name based SimpleMode
            //
            case 9: {
                setResult(
                    new ExtendMode(getLeftIToken(), getRightIToken(),
                                   (Name)getRhsSym(1),
                                   (ISimpleMode)getRhsSym(3))
                );
                break;
            }
            //
            // Rule 10:  ModeName ::= SimpleMode
            //
            case 10:
                break;
            //
            // Rule 11:  ModeName ::= Name
            //
            case 11:
                break;
            //
            // Rule 12:  RuleSemanticsBody ::= Expression
            //
            case 12:
                break;
            //
            // Rule 13:  Expression ::= CommaExpr
            //
            case 13:
                break;
            //
            // Rule 14:  Expression ::= SingleExpr
            //
            case 14:
                break;
            //
            // Rule 15:  CommaExpr ::= Expression ; SingleExpr
            //
            case 15: {
                setResult(
                    new CommaExpr(getLeftIToken(), getRightIToken(),
                                  (IExpression)getRhsSym(1),
                                  (ISingleExpr)getRhsSym(3))
                );
                break;
            }
            //
            // Rule 16:  SingleExpr ::= LogicSemanticsExpr
            //
            case 16:
                break;
            //
            // Rule 17:  SingleExpr ::= IfExpr
            //
            case 17:
                break;
            //
            // Rule 18:  SingleExpr ::= { CommaExpr }
            //
            case 18: {
                setResult(
                    new SingleExpr(getLeftIToken(), getRightIToken(),
                                   (CommaExpr)getRhsSym(2))
                );
                break;
            }
            //
            // Rule 19:  IfExpr ::= if LogicSemanticsExpr then SingleExpr endif
            //
            case 19: {
                setResult(
                    new IfExpr0(getLeftIToken(), getRightIToken(),
                                (ILogicSemanticsExpr)getRhsSym(2),
                                (ISingleExpr)getRhsSym(4))
                );
                break;
            }
            //
            // Rule 20:  IfExpr ::= if LogicSemanticsExpr then SingleExpr else SingleExpr endif
            //
            case 20: {
                setResult(
                    new IfExpr1(getLeftIToken(), getRightIToken(),
                                (ILogicSemanticsExpr)getRhsSym(2),
                                (ISingleExpr)getRhsSym(4),
                                (ISingleExpr)getRhsSym(6))
                );
                break;
            }
            //
            // Rule 21:  LogicSemanticsExpr ::= AndExpr
            //
            case 21:
                break;
            //
            // Rule 22:  LogicSemanticsExpr ::= OrExpr
            //
            case 22:
                break;
            //
            // Rule 23:  LogicSemanticsExpr ::= BooleanExpr
            //
            case 23:
                break;
            //
            // Rule 24:  AndExpr ::= BooleanExpr$LeftExpr and BooleanExpr$RightExpr
            //
            case 24: {
                setResult(
                    new AndExpr(getLeftIToken(), getRightIToken(),
                                (IBooleanExpr)getRhsSym(1),
                                (IBooleanExpr)getRhsSym(3))
                );
                break;
            }
            //
            // Rule 25:  OrExpr ::= BooleanExpr$LeftExpr or BooleanExpr$RightExpr
            //
            case 25: {
                setResult(
                    new OrExpr(getLeftIToken(), getRightIToken(),
                               (IBooleanExpr)getRhsSym(1),
                               (IBooleanExpr)getRhsSym(3))
                );
                break;
            }
            //
            // Rule 26:  BooleanExpr ::= NotExpr
            //
            case 26:
                break;
            //
            // Rule 27:  BooleanExpr ::= ExistoneExpr
            //
            case 27:
                break;
            //
            // Rule 28:  BooleanExpr ::= ForallExpr
            //
            case 28:
                break;
            //
            // Rule 29:  BooleanExpr ::= BasicBooleanExpr
            //
            case 29:
                break;
            //
            // Rule 30:  NotExpr ::= not BooleanExpr
            //
            case 30: {
                setResult(
                    new NotExpr(getLeftIToken(), getRightIToken(),
                                (IBooleanExpr)getRhsSym(2))
                );
                break;
            }
            //
            // Rule 31:  ExistoneExpr ::= AtomicExpr -> existone { Name | Expression }
            //
            case 31: {
                setResult(
                    new ExistoneExpr(getLeftIToken(), getRightIToken(),
                                     (IAtomicExpr)getRhsSym(1),
                                     (Name)getRhsSym(5),
                                     (IExpression)getRhsSym(7))
                );
                break;
            }
            //
            // Rule 32:  ForallExpr ::= AtomicExpr -> forall { Name | Expression }
            //
            case 32: {
                setResult(
                    new ForallExpr(getLeftIToken(), getRightIToken(),
                                   (IAtomicExpr)getRhsSym(1),
                                   (Name)getRhsSym(5),
                                   (IExpression)getRhsSym(7))
                );
                break;
            }
            //
            // Rule 33:  BasicBooleanExpr ::= EqualExpr
            //
            case 33:
                break;
            //
            // Rule 34:  BasicBooleanExpr ::= BooleanFactorExpr
            //
            case 34:
                break;
            //
            // Rule 35:  EqualExpr ::= BooleanFactorExpr$LeftExpr = BooleanFactorExpr$RightExpr
            //
            case 35: {
                setResult(
                    new EqualExpr(getLeftIToken(), getRightIToken(),
                                  (IBooleanFactorExpr)getRhsSym(1),
                                  (IBooleanFactorExpr)getRhsSym(3))
                );
                break;
            }
            //
            // Rule 36:  BooleanFactorExpr ::= EvalExpr
            //
            case 36:
                break;
            //
            // Rule 37:  BooleanFactorExpr ::= OperationSemanticsExpr
            //
            case 37:
                break;
            //
            // Rule 38:  EvalExpr ::= evaluate ( AtomicExpr$DomainPart , UserDefinedVarExpr$BaseContextPar , ModeName )
            //
            case 38: {
                setResult(
                    new EvalExpr(getLeftIToken(), getRightIToken(),
                                 (IAtomicExpr)getRhsSym(3),
                                 (UserDefinedVarExpr)getRhsSym(5),
                                 (IModeName)getRhsSym(7))
                );
                break;
            }
            //
            // Rule 39:  ExclusiveExpr ::= exclusiveVars ( AtomicExpr$DomainPart , AtomicExpr$DomainListPart , AtomicExpr$EnvPart )
            //
            case 39: {
                setResult(
                    new ExclusiveExpr(getLeftIToken(), getRightIToken(),
                                      (IAtomicExpr)getRhsSym(3),
                                      (IAtomicExpr)getRhsSym(5),
                                      (IAtomicExpr)getRhsSym(7))
                );
                break;
            }
            //
            // Rule 40:  UnionExpr ::= union ( AtomicExpr$FirstPart , AtomicExpr$SecoundPart )
            //
            case 40: {
                setResult(
                    new UnionExpr(getLeftIToken(), getRightIToken(),
                                  (IAtomicExpr)getRhsSym(3),
                                  (IAtomicExpr)getRhsSym(5))
                );
                break;
            }
            //
            // Rule 41:  OperationSemanticsExpr ::= AtomicExpr
            //
            case 41:
                break;
            //
            // Rule 42:  OperationSemanticsExpr ::= NewExpr
            //
            case 42:
                break;
            //
            // Rule 43:  OperationSemanticsExpr ::= DeleteExpr
            //
            case 43:
                break;
            //
            // Rule 44:  OperationSemanticsExpr ::= AssignExpr
            //
            case 44:
                break;
            //
            // Rule 45:  AssignExpr ::= Name :: = OperationSemanticsExpr
            //
            case 45: {
                setResult(
                    new AssignExpr(getLeftIToken(), getRightIToken(),
                                   (Name)getRhsSym(1),
                                   (IOperationSemanticsExpr)getRhsSym(4))
                );
                break;
            }
            //
            // Rule 46:  NewExpr ::= new ( AtomicExpr$VarPart , AtomicExpr$ModelPart , AtomicExpr$DomainPart , UserDefinedVarExpr$BaseContextPart )
            //
            case 46: {
                setResult(
                    new NewExpr(getLeftIToken(), getRightIToken(),
                                (IAtomicExpr)getRhsSym(3),
                                (IAtomicExpr)getRhsSym(5),
                                (IAtomicExpr)getRhsSym(7),
                                (UserDefinedVarExpr)getRhsSym(9))
                );
                break;
            }
            //
            // Rule 47:  DeleteExpr ::= delete ( AtomicExpr )
            //
            case 47: {
                setResult(
                    new DeleteExpr(getLeftIToken(), getRightIToken(),
                                   (IAtomicExpr)getRhsSym(3))
                );
                break;
            }
            //
            // Rule 48:  AtomicExpr ::= MatchExpr
            //
            case 48:
                break;
            //
            // Rule 49:  AtomicExpr ::= AttributeExpr
            //
            case 49:
                break;
            //
            // Rule 50:  AtomicExpr ::= OperationExpr
            //
            case 50:
                break;
            //
            // Rule 51:  AtomicExpr ::= VariableExpr
            //
            case 51:
                break;
            //
            // Rule 52:  AtomicExpr ::= ConstExpr
            //
            case 52:
                break;
            //
            // Rule 53:  AtomicExpr ::= ParenAtomicExpr
            //
            case 53:
                break;
            //
            // Rule 54:  AtomicExpr ::= ExclusiveExpr
            //
            case 54:
                break;
            //
            // Rule 55:  AtomicExpr ::= UnionExpr
            //
            case 55:
                break;
            //
            // Rule 56:  ParenAtomicExpr ::= ( Expression )
            //
            case 56: {
                setResult(
                    new ParenAtomicExpr(getLeftIToken(), getRightIToken(),
                                        (IExpression)getRhsSym(2))
                );
                break;
            }
            //
            // Rule 57:  VariableExpr ::= PredefinedVarExpr
            //
            case 57:
                break;
            //
            // Rule 58:  VariableExpr ::= UserDefinedVarExpr
            //
            case 58:
                break;
            //
            // Rule 59:  PredefinedVarExpr ::= transformation
            //
            case 59: {
                setResult(
                    new PredefinedVarExpr0(getRhsIToken(1))
                );
                break;
            }
            //
            // Rule 60:  PredefinedVarExpr ::= rule
            //
            case 60: {
                setResult(
                    new PredefinedVarExpr1(getRhsIToken(1))
                );
                break;
            }
            //
            // Rule 61:  PredefinedVarExpr ::= env
            //
            case 61: {
                setResult(
                    new PredefinedVarExpr2(getRhsIToken(1))
                );
                break;
            }
            //
            // Rule 62:  PredefinedVarExpr ::= trace
            //
            case 62: {
                setResult(
                    new PredefinedVarExpr3(getRhsIToken(1))
                );
                break;
            }
            //
            // Rule 63:  UserDefinedVarExpr ::= IDENTIFIER
            //
            case 63: {
                setResult(
                    new UserDefinedVarExpr(getRhsIToken(1))
                );
                break;
            }
            //
            // Rule 64:  Name ::= IDENTIFIER
            //
            case 64: {
                setResult(
                    new Name(getRhsIToken(1))
                );
                break;
            }
            //
            // Rule 65:  ConstExpr ::= StringConst
            //
            case 65:
                break;
            //
            // Rule 66:  ConstExpr ::= IntConst
            //
            case 66:
                break;
            //
            // Rule 67:  ConstExpr ::= RealConst
            //
            case 67:
                break;
            //
            // Rule 68:  ConstExpr ::= NullConst
            //
            case 68:
                break;
            //
            // Rule 69:  ConstExpr ::= InvalidConst
            //
            case 69:
                break;
            //
            // Rule 70:  ConstExpr ::= BooleanConst
            //
            case 70:
                break;
            //
            // Rule 71:  BooleanConst ::= true
            //
            case 71: {
                setResult(
                    new BooleanConst0(getRhsIToken(1))
                );
                break;
            }
            //
            // Rule 72:  BooleanConst ::= false
            //
            case 72: {
                setResult(
                    new BooleanConst1(getRhsIToken(1))
                );
                break;
            }
            //
            // Rule 73:  StringConst ::= STRING_LITERAL
            //
            case 73: {
                setResult(
                    new StringConst(getRhsIToken(1))
                );
                break;
            }
            //
            // Rule 74:  IntConst ::= INTEGER_LITERAL
            //
            case 74: {
                setResult(
                    new IntConst(getRhsIToken(1))
                );
                break;
            }
            //
            // Rule 75:  RealConst ::= REAL_LITERAL
            //
            case 75: {
                setResult(
                    new RealConst(getRhsIToken(1))
                );
                break;
            }
            //
            // Rule 76:  NullConst ::= null
            //
            case 76: {
                setResult(
                    new NullConst(getRhsIToken(1))
                );
                break;
            }
            //
            // Rule 77:  InvalidConst ::= invalid
            //
            case 77: {
                setResult(
                    new InvalidConst(getRhsIToken(1))
                );
                break;
            }
            //
            // Rule 78:  MatchExpr ::= match [ full ] ( AtomicExpr$DomainPart , UserDefinedVarExpr$BaseContextPart )
            //
            case 78: {
                setResult(
                    new FullMatchExpr(getLeftIToken(), getRightIToken(),
                                      (IAtomicExpr)getRhsSym(6),
                                      (UserDefinedVarExpr)getRhsSym(8))
                );
                break;
            }
            //
            // Rule 79:  MatchExpr ::= match [ partial ] ( AtomicExpr$DomainPart , UserDefinedVarExpr$BaseContextPart )
            //
            case 79: {
                setResult(
                    new PartialMatchExpr(getLeftIToken(), getRightIToken(),
                                         (IAtomicExpr)getRhsSym(6),
                                         (UserDefinedVarExpr)getRhsSym(8))
                );
                break;
            }
            //
            // Rule 80:  AttributeExpr ::= AtomicExpr . Name
            //
            case 80: {
                setResult(
                    new AttributeExpr(getLeftIToken(), getRightIToken(),
                                      (IAtomicExpr)getRhsSym(1),
                                      (Name)getRhsSym(3))
                );
                break;
            }
            //
            // Rule 81:  OperationExpr ::= AtomicExpr . Name ( Params )
            //
            case 81: {
                setResult(
                    new OperationExpr(getLeftIToken(), getRightIToken(),
                                      (IAtomicExpr)getRhsSym(1),
                                      (Name)getRhsSym(3),
                                      (IParams)getRhsSym(5))
                );
                break;
            }
            //
            // Rule 82:  Params ::= Params , Param
            //
            case 82: {
                setResult(
                    new Params(getLeftIToken(), getRightIToken(),
                               (IParams)getRhsSym(1),
                               (IParam)getRhsSym(3))
                );
                break;
            }
            //
            // Rule 83:  Params ::= Param
            //
            case 83:
                break;
            //
            // Rule 84:  Params ::= $Empty
            //
            case 84: {
                setResult(null);
                break;
            }
            //
            // Rule 85:  Param ::= OperationSemanticsExpr
            //
            case 85:
                break;
    
            default:
                break;
        }
        return;
    }
}

